home *** CD-ROM | disk | FTP | other *** search
- #include <Types.h>
- #include <Traps.h>
- #include <SetupA4.h>
- #include <Files.h>
-
- #define _NSetTrapAddress 0xA247 /* from Think Reference; not defined in Traps.h */
-
- /*******************************************************************************
-
- Typedefs.
-
- *******************************************************************************/
- typedef pascal short (*HOpenResFileProc)(short vRefNum,
- long dirID,
- ConstStr255Param fn,
- char permission);
- typedef pascal void (*CloseResFileProc)(short refNum);
- typedef pascal void (*NSetTrapAddressProc)(long trapAddr, short trapNum, short trapType);
- typedef pascal void (*LaunchProc)(void);
-
- /*******************************************************************************
-
- Globals.
-
- *******************************************************************************/
- HOpenResFileProc gOldHOpenResFileAddress;
- CloseResFileProc gOldCloseResFileAddress;
- NSetTrapAddressProc gOldNSetTrapAddressAddress;
- LaunchProc gOldLaunchAddress;
-
- short gCounter;
- Str255 gInitName;
-
- /*******************************************************************************
-
- Function prototypes. Each trap patched should have a new function with
- the same parms as the original trap.
-
- *******************************************************************************/
-
- void main(void);
- pascal void DrawIt(StringPtr theString);
- StringPtr NumToPStr(short n); /* from NumToPStr.c */
- StringPtr StrPCat(StringPtr a, StringPtr b); /* from NumToPStr.c */
-
- /*** HOpenResFile ***/
- pascal short MyHOpenResFile(short vRefNum,
- long dirID,
- ConstStr255Param fn,
- char permission);
- /*** CloseResFile ***/
- pascal void MyCloseResFile(short refNum);
- /*** NSetTrapAddress ***/
- pascal void MyNSetTrapAddress(long trapAddr, short trapNum, short trapType);
- /*** Launch ***/
- pascal void MyLaunch(void);
-
- /*******************************************************************************
-
- main
-
- When INITs are loaded, the operating system jumps to the first byte in the
- resource to execute them. Under THINK C, the compiler adds a little
- snippet of code at the beginning of the INIT that jumps to main(), which
- means that main() can appear anywhere in the source. Under MPW, this isn’t
- done for you, so you have to make sure that main() is the first procedure
- in your source code.
-
- In order for INITs to stay resident, they must be loaded into the System
- heap. Because they contain executable instructions that can be called at
- any time, the INIT resource should be locked. Since they’ll remain locked
- during the entire time the computer is on, they should be loaded as low in
- the heap as possible to prevent fragmentation. Setting the resSysHeap and
- resLocked bits of our INIT resource will do this for us. However, none of
- this prevents our INIT resource from being removed from memory as soon as
- the file it’s in is closed. Therefore, the first thing our main() routine
- does detach the INIT from the resource file.
-
- Next, we plug ourselves into the HOpenResFile() routine. This is done in two
- steps. First, we get the address of the current HOpenResFile() routine and save
- it. Then we install the address of our own custom routine.
-
- *******************************************************************************/
- void main()
- {
- Ptr ourAddress;
-
- RememberA0();
- SetUpA4();
-
- asm {
- move.l A0, ourAddress ; A0 points to the beginning of the
- ; INIT, courtesy of the THINK glue
- }
- DetachResource(RecoverHandle(ourAddress));
-
- gOldHOpenResFileAddress = (HOpenResFileProc) GetToolTrapAddress(_HOpenResFile);
- SetToolTrapAddress((long) MyHOpenResFile, _HOpenResFile);
- gOldCloseResFileAddress = (CloseResFileProc) GetToolTrapAddress(_CloseResFile);
- SetToolTrapAddress((long) MyCloseResFile, _CloseResFile);
- gOldNSetTrapAddressAddress = (NSetTrapAddressProc) GetOSTrapAddress(_NSetTrapAddress);
- SetOSTrapAddress((long) MyNSetTrapAddress, _NSetTrapAddress);
- gOldLaunchAddress = (LaunchProc) GetToolTrapAddress(_Launch);
- SetToolTrapAddress((long) MyLaunch, _Launch);
- RestoreA4();
- }
-
- /*******************************************************************************
-
- MyHOpenResFile
-
- This the patch that gets called whenever any application calls HOpenResFile.
- We check if they are opening an INIT. If so, we want to do our thing.
-
- Under the THINK environments, you are allowed to have global variables in
- standalone code as long as you call SetUpA4() first. Since we’ve stored
- the address of the original HOpenResFile routine in a global, the first we do
- is call SetUpA4(). Then we call the original HOpenResFile so that it can do its
- processing.
-
- Next, it’s time for our custom code to step in.
-
- *******************************************************************************/
- pascal short MyHOpenResFile(short vRefNum,
- long dirID,
- ConstStr255Param fn,
- char permission)
- {
- short result;
- FInfo fndrInfo;
- OSErr iErr;
-
- SetUpA4();
-
- gCounter = -1; /* -1 means don't track it */
-
- iErr = HGetFInfo(vRefNum, dirID, fn, &fndrInfo);
- if ( (iErr == noErr) &&
- (fndrInfo.fdType == 'INIT') ||
- (fndrInfo.fdType == 'cdev') ) {
- gCounter = 0; /* clear our global counter */
- BlockMove(fn, gInitName, *fn+1);
- }
-
- result = gOldHOpenResFileAddress(vRefNum, dirID, fn, permission);
-
- RestoreA4();
-
- return result;
- }
-
-
- /*******************************************************************************
-
- MyCloseResFile
-
- This the patch that gets called whenever any application calls CloseResFile.
- We check if they are opening an INIT. If so, we want to do our thing.
-
- Under the THINK environments, you are allowed to have global variables in
- standalone code as long as you call SetUpA4() first. Since we’ve stored
- the address of the original CloseResFile routine in a global, the first we do
- is call SetUpA4(). Then we call the original CloseResFile so that it can do its
- processing.
-
- Next, it’s time for our custom code to step in.
-
- *******************************************************************************/
- pascal void MyCloseResFile(short refNum)
- {
- StringPtr numString;
- SetUpA4();
-
- if (gCounter != -1) {
- numString = NumToPStr(gCounter);
- numString = StrPCat(gInitName, NumToPStr(gCounter));
- DrawIt(numString);
- while (!Button()) {} ;
- while (Button()) {};
- }
- gOldCloseResFileAddress(refNum);
-
- RestoreA4();
- }
-
-
- /*******************************************************************************
-
- MyNSetTrapAddress
-
- This the patch that gets called whenever any application calls NSetTrapAddress.
- We check if they are opening an INIT. If so, we want to do our thing.
-
- Under the THINK environments, you are allowed to have global variables in
- standalone code as long as you call SetUpA4() first. Since we’ve stored
- the address of the original NSetTrapAddress routine in a global, the first we do
- is call SetUpA4(). Then we call the original NSetTrapAddress so that it can do its
- processing.
-
- Next, it’s time for our custom code to step in.
-
- *******************************************************************************/
- pascal void MyNSetTrapAddress(long trapAddr, short trapNum, short trapType)
- {
- NSetTrapAddressProc nextLink;
- short trapWord;
- short callerTrapWord; // the trap word used to make this call is in d1
-
- asm {
- movem.l a0-a5/d0-d7,-(sp)
- move.w d0,trapWord
- move.w d1,callerTrapWord
- }
-
- SetUpA4();
- nextLink = gOldNSetTrapAddressAddress;
-
- if (gCounter != -1)
- gCounter++;
-
- asm{
- move.l (sp)+,a4 ; same as RestoreA4()
- movem.l (sp)+,a0-a5/d0-d7
- move.l nextLink,a1
- unlk a6
- jmp (a1)
- }
- }
-
-
-
- /*******************************************************************************
-
- MyLaunch
-
- This the patch that gets called whenever any application calls Launch.
-
- Under the THINK environments, you are allowed to have global variables in
- standalone code as long as you call SetUpA4() first. Since we’ve stored
- the address of the original Launch routine in a global, the first we do
- is call SetUpA4(). Then we call the original Launch so that it can do its
- processing.
-
- Next, it’s time for our custom code to step in.
-
- *******************************************************************************/
- pascal void MyLaunch()
- {
- LaunchProc nextLink;
-
- asm {
- movem.l a0-a5/d0-d7,-(sp)
- }
-
- SetUpA4();
- nextLink = gOldLaunchAddress;
-
- SetToolTrapAddress((long) gOldHOpenResFileAddress, _HOpenResFile);
- SetToolTrapAddress((long) gOldCloseResFileAddress, _CloseResFile);
- SetOSTrapAddress((long) gOldNSetTrapAddressAddress, _NSetTrapAddress);
- SetToolTrapAddress((long) gOldLaunchAddress, _Launch);
-
- asm{
- move.l (sp)+,a4 ; same as RestoreA4()
- movem.l (sp)+,a0-a5/d0-d7
- move.l nextLink,a1
- unlk a6
- jmp (a1)
- }
- }
-
-
-
- /*******************************************************************************
-
- DrawIt
-
- Initialize a QuickDraw
-
- *******************************************************************************/
- #include <QuickDraw.h>
-
- typedef struct QuickDraw { /* struct to hold QuickDraw globals */
- char private[76];
- long randSeed;
- BitMap screenBits;
- Cursor arrow;
- Pattern dkGray;
- Pattern ltGray;
- Pattern gray;
- Pattern black;
- Pattern white;
- GrafPtr thePort;
- } QuickDraw;
-
- pascal void DrawIt(StringPtr theString)
- {
- GrafPort myPort; /* port we draw into */
- QuickDraw qdGlobals; /* our own personal QD globals... */
- Rect theRect = {145, 240, 165, 440};
-
- SetUpA4();
- InitGraf(&qdGlobals.thePort); /* initialize our qdGlobals structure */
- OpenPort(&myPort);
- SetPort(&myPort);
- InitFonts();
-
- MoveTo(240,160);
- EraseRect(&theRect);
- DrawString(theString);
- RestoreA4();
- }